## @package auto_log
#  Module auto_log for working with different logs. @author Ivan Filippov (filippov@paragon-software.com)
#  
#  @file auto_log.py source file for module auto_log
import time
import os
import codecs
import subprocess
import sys

STATUS_OK = "Completed successfully"
STATUS_ERROR = "Failed with error"

LOG_TO_STDOUT = "STDOUT"
LOG_TO_NONE = ""

ID_EVT_CLEAR_SYSTEM = "evt_clear_system"
ID_EVT_SAFE_SYSTEM = "evt_safe_system"
ID_EVT_CLEAR_APPLICATION = "evt_clear_application"
ID_EVT_SAFE_APPLICATION = "evt_safe_application"
ID_MSI_FILE_PATH_FROM_LOG = "msi_file_path_from_log"
ID_MSI_MSIEXEC_RESULT = "msi_msiexec_result"
ID_MSI_GUID_FROM_LOG = "msi_guid_from_log"
ID_MSI_FILES_LIST_FROM_LOG = "msi_files_list_from_log"
ID_HDM_PARSE_STUBACT = "hdm_parse_stubact"


## <b>Description:</b> The function writes message in xml like format.
#  
#  The function writes message in xml like format.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param path
#  string value = path to file for saving message. also can be LOG_TO_STDOUT - print to screen or LOG_TO_NONE - no logging
#  @param message
#  string value = message for writing
#  @param status
#  string value = can be STATUS_OK or STATUS_ERROR or custom STATUS.
#  @param id
#  string value = identification of message. default value is "information"
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import write_result
#
#write_result("c:\\log.xml", "Operation completed successfully", auto_log.STATUS_OK, "check resize")
#write_result(auto_log.LOG_TO_STDOUT, "Operation completed with errors", auto_log.STATUS_ERROR, "check format")
#@endcode
def write_result(path, message, status, id = "information"):
    #--------------------------------------------------
    if path == LOG_TO_NONE:
        return 0
    #--------------------------------------------------
    if path == LOG_TO_STDOUT:
        try:
            print("\nmessage id = " + id, "\nstatus = " + status, "\nmessage text = " + message)
            return(0)
        except:
            print("Can't write message to STDOUT")
            return(-1)
    #--------------------------------------------------
    import xml.etree.ElementTree as etree
    try:
        tree = etree.parse(path)
        root = tree.getroot()
    except:
        root = etree.Element("autotest_log")
    
    record = etree.SubElement(root, "record")
    record.set("status", status)
    record.set("id", id)
    record.set("time", str(time.time()))
    record.text = message
    tree = etree.ElementTree(root)
    tree.write(path)
    
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function runs cmd command.
#  
#  This is old version. Use get_cmd_output2 instead.<br>
#  The function runs cmd command.
#  The function returns dictionary value {"err": error, "out": data}<br>
#  "err" integer value = cmd command error code.<br>
#  "out" string value = cmd command output
#  @param cmd_command
#  string value = cmd command
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import get_cmd_output
#
#result = get_cmd_output("chkdsk e: /f /x")
#if result["err"] != 0:
#    print("chkdsk has found errors! chkdsk output = " + result["out"])
#else:
#    print("chkdsk has found no errors!")
#@endcode
def get_cmd_output(cmd_command):
    #--------------------------------------------------
    path_name = "get_cmd_output_" + str(time.time()) + ".txt"
    command = cmd_command + " > " + path_name
    error = os.system(command)
    #--------------------------------------------------
    file = open(path_name, "r")
    data = file.read()
    file.close()
    #--------------------------------------------------
    stop = 0
    while stop != 1:
        try:
            os.remove(path_name)
            stop = 1
        except:
            time.sleep(5)
    #--------------------------------------------------
    result = {"err": error, "out": data}
    return result
#----------------------------------------------------------------------

## <b>Description:</b> The function runs cmd command.
#  
#  The function runs cmd command.
#  The function returns dictionary value {"err": error, "out": data}<br>
#  "err" integer value = cmd command error code.<br>
#  "out" string value = cmd command output
#  @param cmd_command
#  string value = cmd command
#  @param encoding
#  string value = encoding. by default encoding=sys.stdout.encoding
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import get_cmd_output2
#
#result = get_cmd_output2("chkdsk e: /f /x")
#if result["err"] != 0:
#    print("chkdsk has found errors! chkdsk output = " + result["out"])
#else:
#    print("chkdsk has found no errors!")
#@endcode
def get_cmd_output2(cmd_command, encoding=sys.stdout.encoding):
    p = subprocess.Popen(cmd_command, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    out, err = p.communicate()
    out = out.decode(encoding)
    out = out.replace("\r\n", "\n")
    out = out.replace("\r", "\n")
    result = {"err": p.returncode, "out": out}
    return result
#----------------------------------------------------------------------

## <b>Description:</b> The function clears system events log.
#  
#  The function clears system events log.
#  In case of success the function returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param psloglist
#  string value = path to psloglist.exe
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import evt_clear_system
#
#psloglist = "c:\\utils\\psloglist.exe"
#result = evt_clear_system(psloglist)
#if result != 0:
#    print("Can not clear system events log. Error = " + result)
#else:
#    print("Successfully cleared system events log!")
#@endcode
def evt_clear_system(psloglist, log = LOG_TO_STDOUT):
    id = ID_EVT_CLEAR_SYSTEM
    #--------------------------------------------------
    if not os.path.exists(psloglist):
        message = "Can't clear system evt log.\nCan't open " + psloglist
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    clear_system = '"%s" system -c -accepteula' % (psloglist)
    result = get_cmd_output2(clear_system)
    if result["err"] != 0:
        message = "Can't clear system evt log"
        message = message + "\npsloglist error = " + str(result["err"])
        message = message + "\npsloglist output = " + result["out"]
        write_result(log, message, STATUS_ERROR, id)
        return message
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function saves system events log.
#  
#  The function saves system events log.
#  In case of success the function returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param psloglist
#  string value = path to psloglist.exe
#  @param system_log
#  string value = path to file for saving system events log
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import evt_safe_system
#
#psloglist = "c:\\utils\\psloglist.exe"
#result = evt_safe_system(psloglist, "c:\\logs\\system_events.log")
#if result != 0:
#    print("Can not save system events log. Error = " + result)
#else:
#    print("Successfully saved system events log!")
#@endcode
def evt_safe_system(psloglist, system_log, log = LOG_TO_STDOUT):
    id = ID_EVT_SAFE_SYSTEM
    #--------------------------------------------------
    if not os.path.exists(psloglist):
        message = "Can't safe system evt log.\nCan't open " + psloglist
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    safe_system = '"%s" system -accepteula' % (psloglist)
    result = get_cmd_output2(safe_system)
    if result["err"] != 0:
        message = "Can't safe system evt log"
        message = message + "\npsloglist error = " + str(result["err"])
        message = message + "\npsloglist output = " + result["out"]
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    try:
        file = open(system_log, "w")
        file.write(result["out"])
        file.close()
    except:
        message = "Can't safe system evt log"
        message = message + "\nCan't write to " + system_log
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function clears application events log.
#  
#  The function clears application events log.
#  In case of success the function returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param psloglist
#  string value = path to psloglist.exe
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import evt_clear_application
#
#psloglist = "c:\\utils\\psloglist.exe"
#result = evt_clear_application(psloglist)
#if result != 0:
#    print("Can not clear application events log. Error = " + result)
#else:
#    print("Successfully cleared application events log!")
#@endcode
def evt_clear_application(psloglist, log = LOG_TO_STDOUT):
    id = ID_EVT_CLEAR_APPLICATION
    #--------------------------------------------------
    if not os.path.exists(psloglist):
        message = "Can't clear application evt log.\nCan't open " + psloglist
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    clear_application = '"%s" application -c -accepteula' % (psloglist)
    result = get_cmd_output2(clear_application)
    if result["err"] != 0:
        message = "Can't clear application evt log"
        message = message + "\npsloglist error = " + str(result["err"])
        message = message + "\npsloglist output = " + result["out"]
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function saves application events log.
#  
#  The function saves application events log.
#  In case of success the function returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param psloglist
#  string value = path to psloglist.exe
#  @param application_log
#  string value = path to file for saving application events log
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import evt_safe_application
#
#psloglist = "c:\\utils\\psloglist.exe"
#result = evt_safe_system(psloglist, "c:\\logs\\application_events.log")
#if result != 0:
#    print("Can not save application events log. Error = " + result)
#else:
#    print("Successfully saved application events log!")
#@endcode
def evt_safe_application(psloglist, application_log, log = LOG_TO_STDOUT):
    id = ID_EVT_SAFE_APPLICATION
    #--------------------------------------------------
    if not os.path.exists(psloglist):
        message = "Can't safe application evt log.\nCan't open " + psloglist
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    safe_application = '"%s" application -accepteula' % (psloglist)
    result = get_cmd_output2(safe_application)
    if result["err"] != 0:
        message = "Can't safe application evt log"
        message = message + "\npsloglist error = " + str(result["err"])
        message = message + "\npsloglist output = " + result["out"]
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    try:
        file = open(application_log, "w")
        file.write(result["out"])
        file.close()
    except:
        message = "Can't safe application evt log"
        message = message + "\nCan't write to " + application_log
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function gets path to file from msi install log.
#  
#  The function gets path to file from msi install log.
#  In case of success the function returns the dictionary value = {"err": 0, "res": name}.
#  <br>"err" is integer value = 0, "res" is path to file.
#  <br>In case of error the function returns the dictionary value = {"err": message, "res": ""}
#  "err" is string value with error description, "res" is empty string - "".
#  @param log_path_name
#  string value = path to msi install log
#  @param file_name
#  string value = file search name
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import msi_file_path_from_log
#
#result = msi_file_path_from_log("c:\\hdm_msi_install.log", "layout.ini")
#if result["err"] != 0:
#    print("Can't read path from msi log. Error = ", result["err"])
#else:
#    print("Path to layout.ini = ", result["res"])
#@endcode
def msi_file_path_from_log(log_path_name, file_name, log = LOG_TO_STDOUT):
    id = ID_MSI_FILE_PATH_FROM_LOG
    #--------------------------------------------------
    if not os.path.exists(log_path_name):
        message = "Can't open " + log_path_name
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        data = codecs.open(log_path_name, "r", "utf-16").read()
    except:
        message = "Can't read " + log_path_name
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        large_parts = data.split("\\" + file_name + ";")
        parts = large_parts[0].split("File: ")
        result = {"err": 0, "res": (parts[-1] + "\\" + file_name)}
        return result
    except:
        message = "Can't get path to " + file_name
        message = message + " from file " + log_path_name
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
#----------------------------------------------------------------------

## <b>Description:</b> The function returns result of installation from msi install log.
#  
#  The function returns result of installation from msi install log.
#  In case of success the function returns the dictionary value = {"err": 0, "res": data}.
#  <br>"err" is integer value = 0, "res" is installation result.<br>
#  <br>"res" can be:<br><b>"success"</b> - succesfull installation witout reboot<br>
#  <b>"success_reboot_initiated"</b> - succesfull installation witout reboot<br>
#  string value with other installation result.<br>
#  <br>In case of error the function returns the dictionary value = {"err": message, "res": ""}
#  "err" is string value with error description, "res" is empty string - "".
#  @param msi_log
#  string value = path to msi install log
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import msi_msiexec_result
#
#result = msi_msiexec_result("c:\\hdm_msi_install.log")
#if result["err"] != 0:
#    print("Can't read installation result from msi log. Error = ", result["err"])
#elif result["res"] == "success":
#    print("Installation completed successfully without reboot")
#elif result["res"] == "success_reboot_initiated":
#    print("Installation completed successfully with reboot")
#else:
#    print("Installation result = " + result["res"])
#@endcode
def msi_msiexec_result(msi_log, log = LOG_TO_STDOUT):
    #--------------------------------------------------
    id = ID_MSI_MSIEXEC_RESULT
    #--------------------------------------------------
    success = "0"
    success_reboot_initiated = "1641"
    #--------------------------------------------------
    try:
        data = codecs.open(msi_log, "r", "utf-16").read()
    except:
        message = "Can't read " + msi_log
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        large_parts = data.split("MainEngineThread is returning ")
        parts = large_parts[1].split("\n")
    except:
        message = "Can't read result from " + msi_log
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    if parts[0].startswith(success):
        result = {"err": 0, "res": "success"}
        return result
    elif parts[0].startswith(success_reboot_initiated):
        result = {"err": 0, "res": "success_reboot_initiated"}
        return result
    else:
        result = {"err": 0, "res": "error " + parts[0]}
        return result
#----------------------------------------------------------------------

## <b>Description:</b> The function gets product GUID from msi install log.
#  
#  The function gets product GUID from msi install log.
#  In case of success the function returns the dictionary value = {"err": 0, "res": guid}.
#  <br>"err" is integer value = 0, "res" is product GUID.
#  <br>In case of error the function returns the dictionary value = {"err": message, "res": ""}
#  "err" is string value with error description, "res" is empty string - "".
#  @param msi_log
#  string value = path to msi install log
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import msi_guid_from_log
#
#result = msi_guid_from_log("c:\\hdm_msi_install.log")
#if result["err"] != 0:
#    print("Can't read guid from msi log. Error = ", result["err"])
#else:
#    print("GUID = ", result["res"])
#@endcode
def msi_guid_from_log(msi_log, log = LOG_TO_STDOUT):
    id = ID_MSI_GUID_FROM_LOG
    #--------------------------------------------------
    try:
        data = codecs.open(msi_log, "r", "utf-16").read()
    except:
        message = "Can't read " + msi_log
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        guid = "{" + (data.split("{")[1]).split("}")[0] + "}"
    except:
        message = "Can't read guid from " + msi_log
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    result = {"err": 0, "res": guid}
    return result
#----------------------------------------------------------------------

## <b>Description:</b> The function gets list of certain files from msi install log.
#  
#  The function gets list of certain files from msi install log.
#  In case of success the function returns the dictionary value = {"err": 0, "res": list}.
#  <br>"err" is integer value = 0, "res" is list of certain files. path to each file is ending with certain string - for example 
#  if string is equal to ".exe" - we'll get list of all *.exe files
#  <br>In case of error the function returns the dictionary value = {"err": message, "res": []}<br>
#  "err" is string value with error description, "res" is empty list - [].
#  @param path
#  string value = path to msi install log
#  @param name
#  string value = certain string - for example if string is equal to ".exe" - we'll get list of all *.exe files
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import msi_files_list_from_log
#
#result = msi_files_list_from_log("c:\\hdm_msi_install.log", ".dll")
#if result["err"] != 0:
#    print("Can't read list of files from msi log. Error = ", result["err"])
#else:
#    print("List of *.dll files = ")
#    print(result["res"])
#@endcode
def msi_files_list_from_log(path, name, log = LOG_TO_STDOUT):
    id = ID_MSI_FILES_LIST_FROM_LOG
    #--------------------------------------------------
    if not os.path.exists(path):
        message = "Can't open " + path
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        data = codecs.open(path, "r", "utf-16").read()
    except:
        message = "Can't read " + path
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        lines_list = data.split("\n")
        all_files_list = []
        for item in lines_list:
            if (item.count(": File: ") == 1):
                if (item.count("To be installed;") == 1):
                    item = item.split(": File: ")[1]
                    item = item.split("To be installed;")[0]
                    item = item.split(";")[0]
                    all_files_list.append(item)
                elif (item.count("Overwrite;") == 1):
                    item = item.split(": File: ")[1]
                    item = item.split("Overwrite;")[0]
                    item = item.split(";")[0]
                    all_files_list.append(item)
        files_list = []
        for item in all_files_list:
            if item.upper().endswith(name.upper()):
                files_list.append(item)
        result = {"err": 0, "res": files_list}
        return result
    except:
        message = "Can't get list of files from " + path
        write_result(log, message, STATUS_ERROR, id)
        result = {"err": message, "res": []}
        return result
#----------------------------------------------------------------------

## <b>Description:</b> The function parses hdm stubact log.
#  
#  The function parses hdm stubact log.
#  In case of no errors in stubact log the function returns integer value = 0.
#  In other case the function returns the string value with description of errors
#  @param path
#  string value = path to hdm stubact log
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_log import hdm_parse_stubact
#
#path = r"c:\Program Files\Paragon Software\HDM Internal 9\program\stubact.log"
#result = hdm_parse_stubact(path)
#if result != 0:
#    print("Stubact has errors: ", result)
#else:
#    print("Stubact has no errors!")
#@endcode
def hdm_parse_stubact(path, log = LOG_TO_STDOUT):
    id = ID_HDM_PARSE_STUBACT
    #--------------------------------------------------
    try:
        file = open(path, "r")
        data = file.read()
        file.close()
    except:
        message = "Can not read " + path
        write_result(log, message, STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    all_operations_list = data.split("[Operation]\n")[1:]
    operations_list = []
    for item in all_operations_list:
        is_ignore = 0
        #---------------------------------
        item = item.split("___")[0]
        item = item.split("\n#")[0]
        item = item.replace(">> ", "")
        item = item.replace("\n\n", "")
        item = item.replace(" \n", "")
        item = item.replace("DiskVirtual:", "DiskVM:")
        #stupid check - remove RootEnries:
        if item.count("RootEnries:") != 0:
            temp = item.split("RootEn")[1]
            item = item.split("RootEn")[0] + item.split(temp.split("\n")[0] + "\n")[1]
        #---------------------------------
        #stupid check - remove Use alternate boot manager options:
        if item.count("Use alternate boot ") != 0:
            temp = item.split("Use alternate boot ")[1]
            item = item.split("Use alternate boot ")[0] + item.split(temp.split("\n")[0] + "\n")[1]
        #---------------------------------
        #stupid check - remove FSType:
        if item.count("FSTyp") != 0:
            temp = item.split("FSTyp")[1]
            item = item.split("FSTyp")[0] + item.split(temp.split("\n")[0] + "\n")[1]
        #---------------------------------
        item = item.replace("\n", "")
        #---------------------------------
        #List of operations to ignore
        #"Error: 69643 (0x1100B)Restart is needed for operations completion" - ignore operation with restart code
        #"Code: 344 (0x158)" - ignore set archive db operation in BS
        ignore_list = ["Error: 69643 (0x1100B)Restart is needed for operations completion", "Code: 344 (0x158)"]
        for ignore in ignore_list:
            if item.count(ignore) != 0:
                is_ignore = 1
        #---------------------------------
        #another stupid check. remove tail for virtual delete operation
        if item.count("Delete partition") == 1:
            if item.count("Error: 0 (0x0)") == 1:
                item = item.split("Error: 0 (0x0)")[0] + "Error: 0 (0x0)"
        #---------------------------------
        if item not in operations_list:
            if is_ignore == 0:
                operations_list.append(item)
    #--------------------------------------------------
    virtual_list = []
    real_list = []
    for item in operations_list:
        if item.count("Error: 0 ") != 1:
            message = "Error in stubact " + path + "\nOperation:"
            message = message + "\n" + item
            write_result(log, message, STATUS_ERROR, id)
            return message
        if item.count("Virtual: 0 (0x0)") == 1:
            real_list.append(item.replace("Virtual: 0 (0x0)", ""))
        elif item.count("Virtual: 1 (0x1)") == 1:
            virtual_list.append(item.replace("Virtual: 1 (0x1)", ""))
    #--------------------------------------------------
    real_list.sort()
    virtual_list.sort()
    if real_list == virtual_list:
        return 0
    else:
        message = "<b>Parse stubact " + path
        message = message + "\nComparing real and virtual operations failed</b>"
        message = message + "\n\n<b>List of virtual operations:</b>\n\n"
        for item in virtual_list:
            message = message + item + "\n"
        message = message + "\n<b>List of real operations:</b>\n\n"
        for item in real_list:
            message = message + item + "\n"
        write_result(log, message, STATUS_ERROR, id)
        return message
#---------------------------------------------------------------

## @mainpage SCRIPT TEST SYSTEM
#  Set of modules with different functions for testing and automatic testing.
#  <br>
#  <br>
#  <br><b>Modules</b> - list of modules. You can use one or several modules for your needs.
#  <br>
#  <br>auto_log - module for handling different logs
#  <br>auto_vm - module for handling VMWare workstations
#  <br>auto_utility - module with other usefull functions
#  <br>
#  <br>
#  <br><b>Files</b> - list of sources files. You can see here implementation code.
#  <br>
#  <br>auto_log.py - sourse file for module auto_log
#  <br>auto_vm.py - sourse file for module auto_vm
#  <br>auto_utility.py - sourse file for module auto_utility


##  @example simple_performance_test.py Simple performance test with scripts.exe.
#<br>Run each *.psl from scripts_folder N times.
#<br>Save results for each test and average results to log
